package arkham.gui;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DecimalFormat;

import javax.swing.*;

import arkham.util.ImageUtils;
import arkham.util.XmlTools;

public class GameOptionsDialog extends JDialog implements ActionListener
{
	private static final long serialVersionUID = -922041930291536279L;
	private boolean draft;
	private boolean cancelled;
	private JFormattedTextField valueField;
	private JLabel textLabel;
	private int numPlayers;
	private int totalPool;
	private int value;
	private ButtonGroup gameModeChoices;
	
	public GameOptionsDialog(int numPlayers, int poolSize)
	{
		super();
		this.numPlayers = numPlayers;
		this.totalPool = poolSize;
		init();
	}
	
	public GameOptionsDialog(JFrame jf, int numPlayers, int poolSize)
	{
		super(jf);
		this.numPlayers = numPlayers;
		this.totalPool = poolSize;
		init();
	}
	
	/**
	 * Initializes the dialog
	 */
	private void init()
	{
		this.setModalityType(ModalityType.APPLICATION_MODAL);
		setTitle("Select Game Options");
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		cancelled = true;
		draft = false;
		this.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e)
			{
				cancelled = true;
				setVisible(false);
			}
		});
		// set up info panels
		JLabel nptitle = new JLabel("Number of players:   " + numPlayers, JLabel.LEFT);
		JLabel nititle = new JLabel("Total Investigators: " + totalPool, JLabel.LEFT);
		// set up choices
		JRadioButton choiceOption = new JRadioButton("Choice");
		JRadioButton draftOption = new JRadioButton("Draft");
		choiceOption.setSelected(true);
		gameModeChoices = new ButtonGroup();
		choiceOption.setActionCommand("Choice");
		choiceOption.setAlignmentY(BOTTOM_ALIGNMENT);
		draftOption.setActionCommand("Draft");
		choiceOption.addActionListener(this);
		draftOption.addActionListener(this);
		gameModeChoices.add(choiceOption);
		gameModeChoices.add(draftOption);
		valueField = new JFormattedTextField(new DecimalFormat("##"));
		valueField.setAlignmentX(CENTER_ALIGNMENT);
		textLabel = new JLabel("Choices per player:", JLabel.CENTER);
		textLabel.setAlignmentY(BOTTOM_ALIGNMENT);
		// set up buttons
		JButton okButton = new JButton("Ok");
		JButton cancelButton = new JButton("Cancel");
		okButton.setActionCommand("Ok");
		cancelButton.setActionCommand("Cancel");
		okButton.addActionListener(this);
		cancelButton.addActionListener(this);
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
		buttonPanel.add(Box.createHorizontalGlue());
		buttonPanel.add(okButton);
		buttonPanel.add(Box.createHorizontalStrut(15));
		buttonPanel.add(cancelButton);
		buttonPanel.add(Box.createHorizontalGlue());
		// set up grid
		JPanel jp = new JPanel();
		jp.setLayout(new GridBagLayout());
		GridBagConstraints gc = new GridBagConstraints();
		ImageUtils.initGBC(gc, GridBagConstraints.HORIZONTAL, 1, 0, 0, 0);
		gc.gridwidth = 4;
		jp.add(nptitle, gc);
		ImageUtils.initGBC(gc, GridBagConstraints.HORIZONTAL, 1, 0, 0, 1);
		jp.add(nititle, gc);
		ImageUtils.initGBC(gc, GridBagConstraints.BOTH, 0, 0.3, 0, 2);
		gc.gridwidth = 1;
		jp.add(choiceOption, gc);
		ImageUtils.initGBC(gc, GridBagConstraints.HORIZONTAL, 0, 0.3, 0, 3);
		jp.add(draftOption, gc);
		ImageUtils.initGBC(gc, GridBagConstraints.HORIZONTAL, 0.25, 0.3, 1, 3);
		jp.add(Box.createRigidArea(new Dimension(25, 0)), gc);
		ImageUtils.initGBC(gc, GridBagConstraints.HORIZONTAL, 0.5, 0.3, 2, 3);
		jp.add(valueField, gc);
		ImageUtils.initGBC(gc, GridBagConstraints.HORIZONTAL, 0.25, 0.3, 3, 3);
		jp.add(Box.createRigidArea(new Dimension(25, 0)), gc);
		ImageUtils.initGBC(gc, GridBagConstraints.BOTH, 1, 0.3, 1, 2);
		gc.gridwidth = 3;
		jp.add(textLabel, gc);
		ImageUtils.initGBC(gc, GridBagConstraints.HORIZONTAL, 1, 0.4, 0, 4);
		gc.gridwidth = 4;
		jp.add(buttonPanel, gc);
		jp.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
		this.add(jp);
		setSize(200, 150);
		setResizable(false);
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension screensize = toolkit.getScreenSize();
		this.setLocation((screensize.width - 200) / 2, (screensize.height - 180) / 2);
		
	}

	/**
	 * Checks if the game option is set to draft (where all players pick
	 * from a common pool of investigators), or individual choice 
	 * (where each player gets a choice of some investigators, and chooses 1)
	 * @return true if draft is selected, false if ind. choice is selected
	 */
	public boolean isDraft() {
		return draft;
	}
	
	/**
	 * Checks if this window was cancelled
	 * @return true if this was closed by anything other than OK.
	 */
	public boolean isCancelled()
	{
		return cancelled;
	}
	
	/**
	 * Gets the value associated with the game mode. If set to draft, 
	 * this value represents the number of investigators in the draft pool.
	 * If set to choice, this value represents the number of choices each
	 * player gets
	 * @return the value
	 */
	public int getValue() {
		return value;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		String actCmd = e.getActionCommand();
		if (actCmd.equals("Draft") || actCmd.equals("Choice"))
		{
			String selected = gameModeChoices.getSelection().getActionCommand();
			if (selected.equals("Draft"))
			{
				textLabel.setText("Size of pool:");
				draft = true;
			}
			else
			{
				textLabel.setText("Choices per player:");
				draft = false;
			}
		}
		else if (actCmd.equals("Cancel"))
		{
			cancelled = true;
			setVisible(false);
		}
		else if (actCmd.equals("Ok"))
		{
			if (valueField.getText().length() == 0 || !XmlTools.isNumeric(valueField.getText()))
			{
				JOptionPane.showMessageDialog(this, "Must specify an integer.", 
						"Error", JOptionPane.ERROR_MESSAGE);
				return;
			}
			else
			{
				int value = Integer.parseInt(valueField.getText());
				if (value <= 0)
				{
					JOptionPane.showMessageDialog(this, "Value must be positive.", 
							"Error", JOptionPane.ERROR_MESSAGE);
					return;
				}
				if (draft)
				{
					if (value < numPlayers)
					{
						JOptionPane.showMessageDialog(this, "Pool size must be at least the number of players", 
								"Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					if (value > totalPool)
					{
						JOptionPane.showMessageDialog(this, "Pool is too large.", 
								"Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					this.value = value;
					cancelled = false;
					setVisible(false);
				}
				else
				{
					if (value * numPlayers > totalPool)
					{
						JOptionPane.showMessageDialog(this, "Not enough investigators to go around!", 
								"Error", JOptionPane.ERROR_MESSAGE);
						return;
					}
					this.value = value;
					cancelled = false;
					setVisible(false);
				}
			}
		}
	}

}
